package com.thiruvathukal.examples.dom;

/*
 * XML code examples by George K. Thiruvathukal. Unless noted otherwise
 * this code is covered by GPLv2. We are still working on the licensing
 * text and will update all code and documentation shortly.
 */

import java.io.StringWriter;
import java.util.Enumeration;
import java.util.Vector;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;

import com.sun.org.apache.xml.internal.serialize.OutputFormat;
import com.sun.org.apache.xml.internal.serialize.XMLSerializer;

public class Task {

	String name;
	String description;
	Vector subTasks;

	public Task(String name, String description) {
		this.name = name;
		this.description = description;
		this.subTasks = null;
	}

	public Task createSubTask(String name, String description) {
		if (subTasks == null)
			subTasks = new Vector();
		Task newTask = new Task(name, description);
		subTasks.addElement(newTask);
		return newTask;
	}

	public boolean hasSubTasks() {
		return subTasks != null;
	}

	public String toString() {
		StringBuffer sb = new StringBuffer();
		toStringRecursive(sb, 0);
		return sb.toString();
	}

	public void indent(StringBuffer sb, int level) {
		for (int i = 0; i < level * 2; i++)
			sb.append(' ');
	}

	public void newline(StringBuffer sb) {
		sb.append("\n");
	}

	public void toStringRecursive(StringBuffer sb, int level) {
		indent(sb, level);
		sb.append("Task");
		newline(sb);
		indent(sb, level);
		sb.append("name = " + name);
		newline(sb);
		indent(sb, level);
		sb.append("description:");
		newline(sb);
		indent(sb, level);
		sb.append(description);
		newline(sb);
		indent(sb, level);
		if (subTasks != null) {
			sb.append("printing subtasks of task " + name + '('
					+ subTasks.size() + ')');
			newline(sb);
			Enumeration e = subTasks.elements();
			while (e.hasMoreElements()) {
				sb.append("subtask of " + name);
				newline(sb);
				Task t = (Task) e.nextElement();
				t.toStringRecursive(sb, level + 1);
			}
		}
		newline(sb);
	}

	public void toDOM(Document docBuilder) {
		Element docElement = toDOMRecursive(docBuilder);
		docBuilder.appendChild(docElement);
	}

	public Element toDOMRecursive(Document docBuilder) {
		Element newElement = docBuilder.createElement("Task");
		newElement.setAttribute("name", name);
		Node textNode = docBuilder.createTextNode(description);
		newElement.appendChild(textNode);
		if (subTasks != null) {
			Element subTaskElement = docBuilder.createElement("TaskGroup");
			Enumeration e = subTasks.elements();
			while (e.hasMoreElements()) {
				Task t = (Task) e.nextElement();
				Element nestedTaskElement = t.toDOMRecursive(docBuilder);
				subTaskElement.appendChild(nestedTaskElement);
			}
			newElement.appendChild(subTaskElement);
		}
		return newElement;
	}

	public static void main(String args[]) throws ParserConfigurationException {
		Task top = new Task("t1", "t1 desc");
		Task topSubTask = top.createSubTask("t2", "t2 desc");
		topSubTask.createSubTask("t3", "t3 description");
		topSubTask.createSubTask("t4", "t4 description");
		top.createSubTask("t5", "t5 desc");
		System.out.println(top);

		DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
		dbf.setNamespaceAware(false);
		dbf.setValidating(false);
		DocumentBuilder builder = dbf.newDocumentBuilder();
		Document docBuilder = builder.newDocument();
		top.toDOM(docBuilder);
		OutputFormat format = new OutputFormat(docBuilder, "UTF-8", true);
		StringWriter stringOut = new StringWriter();
		XMLSerializer serial = new XMLSerializer(stringOut, format);
		try {
			serial.asDOMSerializer();
			serial.serialize(docBuilder.getDocumentElement());
		} catch (Exception e) {
			System.err.println("Exception " + e);
		}
		System.out.println("XML\n---");
		System.out.println(stringOut.toString());
	}
}